package cn.nr19.jian.token

import cn.nr19.jian.J2Utils
import cn.nr19.jian.`object`.EON

/**
 * 节点
 */
abstract class Node {

    // 所在行 列
    var position = 0
    fun setStartToken(token: Token){
        this.position = token.pos
    }
    abstract fun nodeType() : ENode


    // 注释 一般不用 . 编辑器用
    var notes : String =""

    // 编辑器用
    fun color(color : String,str : String) : String{
        return "<font color='${color}'>${str}</font>"
    }
    open fun toStr(level: Int) : String{
        return toStr(level,getLevelPos(level))
    }
    open fun toStr(level : Int,tabStr :String) : String{
        return tabStr + toString()
    }
    fun getLevelPos(level: Int) : String{
        var t = ""
        for (i in 0 until level){
            t += " "
        }
        return t
    }

    open fun toHtmlStr() : String{
        return toString()
    }

    //  报错显示
    fun toEx() : String{
        val obj = EON()
        // if (notes.isNotEmpty()) obj.put("注释",notes)
        obj.put("类型",nodeType())
        toEex(obj)
        return obj.toString()
    }
    fun pEx(obj : EONNode){
        pEex(obj)
    }

    open fun toEex(obj :EON){}
    open fun pEex(obj : EONNode){}
    open fun gErrotTips(): String? {
        return ""
    }


}

/**
 * 简代码 仅处理了 token
 */
class J2Node() : Node() {

    // 参数变量名
    val vars = ArrayList<String>()

    // 指令 节点值
    val nodes = ArrayList<Node>()

    override fun toStr(level: Int, tabStr: String): String {
        StringBuilder().apply {
            if (vars.isNotEmpty()){
                vars.forEach {
                    append(it).append(",")
                }
                deleteCharAt(length - 1)
                append(" ->\n")

            }

            nodes.forEach {
                append(it.toStr(level)).append("\n")
            }
            return toString()
        }
    }

    override fun toString(): String {
        StringBuilder().apply {
            nodes.forEach {
                append(it).append(";  ")
            }
            return toString()
        }
    }

    override fun nodeType(): ENode {
        return  ENode.j2
    }
}

// 继承  引用 clazz 作 name,  name 就是调用名，跟变量一样调用
class IMPORT : Node{
    var path = ""
    var name = ""
    constructor()
    constructor(path : String){
        this.path = path
        this.name = path
    }
    constructor(token: Token,text: String,name: String){
        setStartToken(token)
        this.path = text
        this.name = name
    }
    override fun nodeType(): ENode = ENode.nimport


    // ----------- 编辑器 -------------------
    var leinode : LeiNode?= null // 引用类属性


    override fun toString(): String {
        return "引用 ${path}"
    }




}
class InNode : Node{
    var path : String = ""
    constructor()
    constructor(s : String){
        this.path = s
    }
    constructor(token: Token,text: String){
        setStartToken(token)
        this.path = text
    }
    init {


    }
    override fun nodeType(): ENode = ENode.nin
    override fun toString(): String {
        return "继承 ${path}"
    }
}




/**
 * 创建变量
 * 变量 : 类型 = 值
 */
class NVarNode(token: Token?=null) : Node() {
    var name = ""
    var type : ParTypeNode?= null
    var value : Node?= null

    init {
        if (token != null) setStartToken(token)
    }
    override fun toString(): String {
        return StringBuilder("变量 ").let {
            it.append(name)
            if (type != null) it.append(":").append(type.toString())
            if (value != null) it.append(" = ").append(value.toString())
            it.toString()
        }
    }

    override fun nodeType(): ENode = ENode.nvar
}

/**
 * 功能(参数):类型{子代码}
 */
class NFunNode : Node{
    constructor(token: Token){
        setStartToken(token)
    }
    constructor()
    var name : String = ""
    var pars = ArrayList<ParNode>()
    var type : ParTypeNode?= null
    var j2 : J2Node?= null

    override fun nodeType(): ENode = ENode.nfun

    override fun toStr(level: Int, tabStr: String): String {
        StringBuilder("功能 ").apply {
            append(tabStr).append(name).append("(")
            if (pars.size>0){
                pars.forEach {
                    append(it).append(",")
                }
                deleteCharAt(length - 1) // 尾部逗号
            }
            append(")")
            if (type != null) append(":").append(type)
            append("{").append("\n")
            append(j2?.toStr(level + 1))
            append(tabStr).append("}")
            return toString()
        }
    }
    override fun toString(): String {
        StringBuilder("功能 ").apply {
            append(name)
            append("(")
            if (pars.size>0){
                pars.forEach {
                    append(it).append(",")
                }
                deleteCharAt(length - 1) // 尾部逗号
            }
            append(")")
            if (type != null) append(":").append(type)
            append("{").append(j2).append("}")
            return toString()
        }
    }
}

/**
 * 事件(参数):类型{子代码}
 */
class NEventNode : Node(){
    //  name,  xx.name , xx[0].name
    var name : String = ""
    var target : Node ?= null // 子属性的事件
    var pars = ArrayList<ParNode>()
    var type : ParTypeNode?= null
    var j2 : J2Node?= null
    override fun nodeType(): ENode = ENode.nevent
    override fun toString(): String {
        StringBuilder("事件 ").apply {
            if (target!=null) append(target).append(".")
            append(name)
            append("(")
            if (pars.size>0){
                pars.forEach {
                    append(it).append(",")
                }
                deleteCharAt(length - 1) // 尾部逗号
            }

            append(")")
            if (type != null) append(":").append(type)
            append("{").append(j2).append("}")
            return toString()
        }
    }

    override fun toStr(level: Int, tabStr: String): String {
        StringBuilder("事件 ").apply {
            append(tabStr)
            if (target!=null) append(target).append(".")
            append(name).append("(")
            if (pars.size>0){
                pars.forEach {
                    append(it).append(",")
                }
                deleteCharAt(length - 1) // 尾部逗号
            }
            append(")")
            if (type != null) append(":").append(type)
            append("{").append("\n")
            append(j2?.toStr(level + 1))
            append(tabStr).append("}")
            return toString()
        }
    }

    // 将参数移到 J2 中，解析用。
    fun par2J2() : J2Node?{
        j2?.let { j2->
            pars.forEach {
                j2.vars.add(it.name)
            }
        }
        return j2
    }
}

/**
 * 循环
 */
class ForNode : Node {
    // 这不能为空
    var left : Node?= null
    var dao = false // 到 true .<  ， false ..
    var right : Node?= null // 为空则循环自身
    var stat : J2Node?= null

    override fun nodeType(): ENode = ENode.nfor

    constructor(l : Node, j2 : J2Node?= null){
        this.left = l
        this.stat = j2
        position= l.position
    }
    constructor(l : Node, right : Node, j2 : J2Node?= null){
        this.left= l
        this.right= right
        this.stat = j2
        position= l.position
    }

    override fun toString(): String {
        StringBuilder().let {
            it.append("循环(")
            it.append(left.toString())
            if (right != null) it.append(if (dao) " .< " else " .. ").append(right)

            it.append("){").append(stat?:"").append("}")

            return it.toString()
        }
    }

    override fun toStr(level: Int, tabStr: String): String {
        StringBuilder().apply {
            append(tabStr).append("循环(")

            append(left.toString())
            if (right != null && right.toString().isNotEmpty()) append(if (dao) " .< " else " .. ").append(right)

            append("){").append("\n")

            if (stat != null) append(stat!!.toStr(level+1))

            append(tabStr).append("}")
            return toString()
        }
    }
}

/**
 * 判断
 */
class WhenNode : Node(){
    /**
     * ifxs[0]==判断值， 然后 ifxs[1] == stat[0]
     * 若 stat.size == ifxs.size 则 最后一个 stat 为否则
     */
    var ifxs = ArrayList<Node>()
    var stats = ArrayList<J2Node>()

    override fun nodeType(): ENode = ENode.nwhen
    override fun toString(): String {
         return toStr(0," ").replace("\n"," ")
    }
    override fun toStr(level: Int, tabStr: String): String {
        if (ifxs.size == 0) return ""
        StringBuilder(tabStr).apply {
            append(tabStr).append("判断(").append(ifxs[0]).append("){").append("\n")

            val tabstr2 = getLevelPos(level+1)

            for (i in 1 until ifxs.size){
                append(tabstr2).append(ifxs.toString()).append( "-> {").append("\n")
                append(stats[i - 1].toStr(level + 2))
                append(tabstr2).append("}").append("\n")
            }

            // 否则
            if (stats.size == ifxs.size){
                append(tabstr2).append( "否则 -> {").append("\n")
                append(stats[stats.size - 1].toStr(level + 2))
                append(tabstr2).append("}").append("\n")
            }

            append(tabStr).append("}")
            return toString()
        }

    }

}

// 判断
class IFNode() : Node(){
    var ifxs = ArrayList<Node>()
    var stats = ArrayList<J2Node>()
    override fun toString(): String {
        if (ifxs.size == 0) return ""
        StringBuilder().let {
            it.append("如果(")
            it.append(ifxs[0])
            it.append("){")
            if (stats.size > 0) it.append(stats[0])

            // 否则如果
            for (i in 1 until stats.size){

                // 超出 ifx 数量，就是否则
                if (ifxs.size == i) {
                    it.append("}否则{").append(stats[i])
                }
                else if (ifxs.size > i){
                    it.append("否则如果(").append(ifxs[i]).append("){").append(stats[i])
                }

            }


            it.append("}")
            return it.toString()
        }
    }
    override fun nodeType(): ENode = ENode.nif

    override fun toStr(level: Int, tabStr: String): String {
        if (ifxs.size == 0) return ""
        StringBuilder(tabStr).apply {
            append("如果(").append(ifxs[0]).append("){").append("\n")

            if (stats.size > 0) append(tabStr).append(stats[0].toStr(0))

            // 否则如果
            for (i in 1 until stats.size){
                // 超出 ifx 数量，就是否则
                if (ifxs.size == i) {
                    append("\n").append(tabStr).append("}否则{").append("\n")
                    append(stats[i].toStr(level+1))
                }
                else if (ifxs.size > i){
                    append("\n").append(tabStr).append("}否则如果(").append(ifxs[i]).append("){").append("\n")
                    append(stats[i].toStr(level+1))
                }
            }
            append("}")
            return toString()
        }

    }


}

class ContinueNode() : Node(){
    override fun nodeType(): ENode = ENode.CONTINUE
    override fun toString(): String {
        return "跳过"
    }
}

// 跳出循环
class BreakNode() : Node(){
    override fun nodeType(): ENode = ENode.BREAK
    override fun toString(): String {
        return "跳出"
    }
}


class ReturnNode : Node {
    var node : Node?= null
    constructor()
    constructor(n : Node){
        this.node = n
    }

    override fun nodeType(): ENode = ENode.RETURN

    override fun toString(): String {
        StringBuilder().apply {
            append("返回 ")
            if (node != null) append(node!!)
            append("; ") // 返回函数后面允许有节点
            return toString()
        }
    }

    override fun toStr(level: Int, tabStr: String): String {
        StringBuilder().apply {
            tabStr + append("返回 ")
            if (node != null) append(node!!)
            append("\n") // 返回函数后面允许有节点
            return toString()
        }

    }



}

/**
 * 取功能
 */
class GFunNode : Node {
    override fun nodeType(): ENode = ENode.gfun
    var name : String = ""
    var pars = ArrayList<Node>()
    var type : ParTypeNode?= null

    constructor()
    constructor(name : String,token: Token){
        this.name = name
        setStartToken(token)
    }


    // 注释

    override fun toString(): String {
         StringBuilder().apply {
            append(name)
            if (type != null) append(":").append(type.toString())
            append("(")
            pars.forEach {
                append(it).append(",")
            }
             if (endsWith(",")) deleteCharAt(length - 1)
            append(")")
            return toString()
        }
    }
}

/**
 * 参数
 * KEY:ParType,
 */
class ParNode : Node {
    override fun nodeType(): ENode = ENode.par
    var name = ""
    var type : ParTypeNode ?= null

    constructor()
    constructor(name :String,type: ParTypeNode?){
        this.name = name
        this.type =type
    }
    constructor(token: Token,type: ParTypeNode?=null){
        this.name = token.text
        setStartToken(token)
        this.type = type
    }

    override fun toString(): String {
        return StringBuilder(name).let {
            if (type != null) it.append(":").append(type)
            it.toString()
        }
    }


}

/**
 * 参数类型
 * 名称
 * xx.class.name  || class<T,K>
 *
 */
class ParTypeNode: Node{
    override fun nodeType(): ENode = ENode.partype

    constructor(token: Token){
        setStartToken(token)
        this.name = token.text
    }
    constructor(name : String){
        this.name = name
    }
    // key
    var name = ""

    // 定义泛类  name<T,K>
    var fans = ArrayList<String>()


    // ***************************************
    // ********* 运行时动态记录  ***************

    // 实际类名 用来反射获取类信息
    var clazz : Class<*> ?= null

    // 引用类数据，编辑时使用，优先级最高。以本数据内容为准。若为空，则根据name读取类数据
    var classData : LeiNode ?= null

    override fun toString(): String {
        StringBuilder(name).apply {
            if (fans.size > 0) {
                append("<")
                fans.forEach {
                    append(it).append(",")
                }
                deleteCharAt(length - 1)
                append(">")
            }
            return toString()
        }
    }



}

// obj[obj]
class Obj1Node(val left: Node, val right: Node) : Node() {
    override fun nodeType(): ENode = ENode.obj1
    //var left : Node ?= l
    //var right : Node ?= r

    override fun toString(): String {
        return "${left}[${right}]"
    }

    init {
        position = left.position
    }
}


// obj.obj
class Obj2Node(val left: Node, val right: Node) : Node() {
    override fun nodeType(): ENode = ENode.obj2
    override fun toString(): String {
        return "${left}.${right}"
    }
    init {
        position = left.position
    }
}


// 运算
class SuanNode : Node {
    override fun nodeType(): ENode = ENode.suan
    var left : Node?= null
    var right : Node?= null
    var ysf : String = ""
    var ysfTokenType = EToken.ysf2
    constructor()
    constructor(l : Node, r : Node, ysf : Token){
        left = l
        right = r
        this.ysfTokenType = ysf.type
        this.ysf = ysf.text
    }
    constructor(l : Node, r : Node, ysfType : EToken,ysf : String){
        left = l
        right = r
        this.ysfTokenType = ysfType
        this.ysf = ysf
    }

    init {
        if (left!=null){
            position = left!!.position
        }
    }
    override fun toString(): String {
        StringBuilder(left.toString()).let {
            it.append(ysf).append(right.toString())
            return it.toString()
        }
    }
}
// 判断
class IFX : Node {
    override fun nodeType(): ENode = ENode.ifx
    var left : Node?= null

    // 运算符
    var ysf : String = "!"  // ! >= > <= < != !==  ==
    var right : Node?= null

    init {
        if (left!=null){
            position = left!!.position
        }
    }

    constructor()
    constructor(v: Node, ysf : String = "!", r : Node?=null){
        this.left = v
        this.ysf = ysf
        this.right = r
    }

    override fun toString(): String {
        return StringBuilder().let {
            if (right == null){
                it.append(ysf).append(left.toString())
            }else{
                it.append(left.toString()).append(ysf).append(right)
            }

            it.toString()
        }

    }
}

// 类型判断  IS: ture=is , false=!is ;
class IFXIS(val left : Node, val IS : Boolean, val right : Node) : Node(){
    init {
        position = left.position
    }
    override fun nodeType(): ENode = ENode.ifxIS
    override fun toString(): String {
        return StringBuilder().let {
            it.append(left.toString()).append(if (IS) " 是 " else " 不是 ").append(right)
            it.toString()
        }
    }
}

// 且 或, or : true =||、或  , false=&&、且
class IFXOR(val left : Node, val OR : Boolean, val right : Node) : Node(){
    init {
        position = left.position
    }
    override fun nodeType(): ENode = ENode.ifxOR
    override fun toString(): String {
        return StringBuilder().let {
            it.append(left.toString()).append(if (OR) " 或 " else " 且 ").append(right)
            it.toString()
        }
    }
}


// 变量自加减
class VARSELF : Node {
    override fun nodeType(): ENode = ENode.varself
    var target : Node?= null // 变量名
    var mode = 0 // 0++, 1--, ++2,--3
    constructor()
    constructor(n : Node, m : Int){
        this.target = n
        this.mode = m
    }

    init {
        if (target!=null){
            position = target!!.position
        }
    }

    override fun toString(): String {
        if (target == null) return ""
        return  when(mode){
            0 -> target.toString() + "++"
            1 -> target.toString() + "--"
            2 -> "++" + target.toString()
            3 -> "--" + target.toString()
            else -> target.toString()
        }
    }
}


// 赋值   left ysmbol(=,+=,-=,*=,/=)
class FuzhiNode  : Node {
    var left:Node ?= null
    var symbol = "="
    var right :Node ?= null
    constructor()
    constructor(left : Node, symbol : String, right : Node){
        this.left = left
        this.right = right
        this.symbol = symbol
        this.position = left.position
    }
    override fun nodeType(): ENode = ENode.fuzhi
    override fun toString(): String {
        StringBuilder().apply {
            append(left).append(" ").append(symbol).append(" ").append(right)
            return toString()
        }

    }

}





